package com.xiaoxiong.gobang.bean;

import android.util.Log;

import com.xiaoxiong.gobang.evaluate.Evaluator;
import com.xiaoxiong.gobang.evaluate.SecondEvaluate;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author xiaoxiong
 * @Package com.xiaoxiong.gobang.bean
 * @Description:棋盘状态
 * @email 249900679@qq.com
 * @date 2016/4/1 17:42
 */
public class GameState {
    private int m_playerId;
    private int[] m_board;
    private int len;
    private Evaluator m_evaluator;
    private int winner;
    private boolean is;
    private static int f[] = {1, 16, 17, 15};
    private Set<Integer> nullPos;
    private Set<Integer> whitePos;
    private Set<Integer> blackPos;
    private List<Integer> canPutPos;

    /**
     * 设置评估算法
     *
     * @param m_evaluator
     */
    public void set_evaluator(Evaluator m_evaluator) {
        this.m_evaluator = m_evaluator;
    }

    /**
     * @return 返回评估值
     */
    public int Evaluate(int position, int depth) {
        if (depth == 1) {
            Log.d("position", position + "");
            return m_evaluator.Evaluate(m_board, position, m_playerId);
        } else if (depth == 2) {
            return new SecondEvaluate().Evaluate(m_board, position, m_playerId);
        } else {
            Set<Integer> nowPos = new HashSet<>();
            if (m_playerId == Player.FIRSTPLAYER) {
                nowPos = blackPos;
            } else {
                nowPos = whitePos;
            }
            return new SecondEvaluate().Evaluate(m_board, position, m_playerId);
        }
    }

    /**
     * 设置先手落子的玩家ID
     *
     * @param playerid 玩家ID
     */
    public void InitGameState(int playerid) {
        this.m_playerId = playerid;
        this.winner = playerid;
        this.m_board = new int[15 * 15 + 34 + 15];
        this.nullPos = new HashSet<>();
        this.whitePos = new HashSet<>();
        this.blackPos = new HashSet<>();
        this.canPutPos = new ArrayList<>();
        for (int i = 0; i < 15; ++i) {
            for (int j = 0; j < 15; ++j) {
                m_board[17 + i + j * 16] = -1;
            }
        }
        this.len = 0;
        this.is = false;
    }

    public void SetBoard(int[] board) {
        this.m_board = board;
    }

    /**
     * 判断是否结束
     *
     * @return
     */
    public boolean IsGameOver() {
        if (this.len == 225) {
            m_playerId = Player.NULLPALYER;
            return true;
        }
        if (is) {
            this.m_playerId = winner;
            return true;
        }

        return false;
    }

    /**
     * 获取赢家ID
     *
     * @return
     */
    public int GetWinner() {
        return m_playerId;
    }

    /**
     * 获取当前玩家ID
     *
     * @return
     */
    public int GetCurrentPlayer() {
        return m_playerId;
    }

    /**
     * 切换当前玩家
     */
    public void SwitchPlayer() {
        m_playerId = (m_playerId == Player.FIRSTPLAYER ? Player.SECONDPLAYER : Player.FIRSTPLAYER);
    }

    /**
     * 在棋盘中放入棋子
     *
     * @param dis    位置
     * @param playid 棋子
     * @return 返回放入棋子后的棋盘
     */
    public int[] PutChess(int dis, int playid) {
        m_board[dis] = playid;
        this.len++;
        Log.i("check2", dis + "");
        check(dis, playid);
        nullPos.remove(dis);
        addNullPos(dis);
        Log.i("size", nullPos.size() + "");
        if (playid == Player.FIRSTPLAYER) {
            blackPos.add(dis);
        } else {
            whitePos.add(dis);
        }

        return m_board;
    }

    /**
     * 在棋盘中放入棋子
     *
     * @param dis 位置
     * @return 返回放入棋子后是否胜利了
     */
    public boolean PutChess(int dis, boolean isMe) {
        if (!isMe) {
            SwitchPlayer();
        }
        m_board[dis] = m_playerId;
        this.len++;
        Log.i("check1", dis + "");
        check(dis, m_playerId);
        nullPos.remove(dis);
        addNullPos(dis);
        if (m_playerId == Player.FIRSTPLAYER) {
            blackPos.add(dis);
        } else {
            whitePos.add(dis);
        }
//        SwitchPlayer();

        return is;
    }

    /**
     * 撤销下棋
     *
     * @param dis
     */
    public void BackChess(int dis, boolean isMe) {
        if (!isMe) {
            SwitchPlayer();
        }
        m_board[dis] = Player.NULLPALYER;
        this.len--;
        is = false;
        nullPos.add(dis);
        delNullPos(dis);
        if (m_playerId == Player.FIRSTPLAYER) {
            blackPos.remove(dis);
        } else {
            whitePos.remove(dis);
        }
    }

    public Set<Integer> getNullPos() {
        return this.nullPos;
    }

    public boolean checkDis(int dis) {
        if (m_board[dis] == Player.NULLPALYER) {
            return true;
        }
        return false;
    }

    /**
     *
     * @param dis
     */
    private void addNullPos(int dis) {

        for (int i = 0; i < f.length; ++i) {
            int c = 0;
            int d = dis + f[i];
            while (m_board[d] == Player.NULLPALYER) {
                c++;
                if(nullPos.contains(d)){
                    canPutPos.add(d);
                }else {
                    nullPos.add(d);
                }
                if(c == 3){
                    break;
                }
                d += f[i];
            }
            c = 0;
            d = dis - f[i];
            while (m_board[d] == Player.NULLPALYER) {
                c++;
                if(nullPos.contains(d)){
                    canPutPos.add(d);
                }else {
                    nullPos.add(d);
                }
                if(c == 3){
                    break;
                }
                d -= f[i];
            }
        }
    }

    private void delNullPos(int dis) {
        for (int i = 0; i < f.length; ++i) {
            int c = 0;
            int d = dis + f[i];
            while (m_board[d] == Player.NULLPALYER) {
                c++;
                nullPos.remove(d);
                if(c == 3){
                    break;
                }
                d += f[i];
            }
            c = 0;
            d = dis - f[i];
            while (m_board[d] == Player.NULLPALYER) {
                c++;
                nullPos.remove(d);
                if(c == 3){
                    break;
                }
                d -= f[i];
            }
        }
        while(!canPutPos.isEmpty()){
            nullPos.add(canPutPos.get(0));
            canPutPos.remove(0);
        }
    }

    private void check(int dis, int playid) {
        for (int i = 0; i < f.length; ++i) {
            int c = 1;
            int d = dis + f[i];
            while (m_board[d] == playid) {
                c++;
                d += f[i];
            }
            d = dis - f[i];
            Log.d("d", d + "");
            while (m_board[d] == playid) {
                c++;
                d -= f[i];
            }
            if (c >= 5) {
                winner = playid;
                Log.d("over", winner + "赢");
                is = true;
                break;
            }
        }
    }
}
